package syncmaster;

import java.util.*;

public class HeartModel implements HeartModelInterface, Runnable {
	//Utiliza el singleton para generar 1 instancia
	private static BeatObserver instanciaSbeat = null;
	private static BPMObserver instanciaSbpm = null;
	
	static ArrayList beatObservers = new ArrayList();
	ArrayList bpmObservers = new ArrayList();
	int ObserversDenied = 0;
	int time = 1000;
    int bpm = 90;
	Random random = new Random(System.currentTimeMillis());
	Thread thread;
	
	//Constructor en modo protected para evitar acceso externo
	protected HeartModel() {
		thread = new Thread(this);
		thread.start();
		
	}

	public void run() {
		int lastrate = -1;

		for(;;) {
			
			notifyBPMObservers();
			int change = random.nextInt(10);
			if (random.nextInt(2) == 0) {
				change = 0 - change;
			}
			int rate = 60000/(time + change);
			if (rate < 120 && rate > 50) {
				time += change;
				notifyBeatObservers();
			}
			try {
				Thread.sleep(time);
			} catch (Exception e) {}
		}
	}
	
	public int getHeartRate() {
		//devuelve cant. de observers denegados
		return ObserversDenied;
	}

	public void registerObserver(BeatObserver o) {
		if(instanciaSbeat == null) {
	         instanciaSbeat = o;
	         beatObservers.add(o);
	    }
	}
	
	//Usado por el Singleton Test
	public static BeatObserver getbeatInstance() {
		return instanciaSbeat;
	}
	
	public void removeObserver(BeatObserver o) {
		int i = beatObservers.indexOf(o);
		if (i >= 0) {
			beatObservers.remove(i);
		}
	}

	public void notifyBeatObservers() {
		for(int i = 0; i < beatObservers.size(); i++) {
			BeatObserver observer = (BeatObserver)beatObservers.get(i);
			observer.updateBeat();
		}
	}

	public void registerObserver(BPMObserver o) {
		if(instanciaSbpm == null) {
	         instanciaSbpm = o;
	         bpmObservers.add(o);
	    }
		else {
			//Contador de observers denegados
			ObserversDenied++;
			System.out.println("Denied! "+ObserversDenied);
		}
	}
	
	//Usado por el Singleton Test
	public static BPMObserver getbpmInstance() {
		return instanciaSbpm;
	}

	public void removeObserver(BPMObserver o) {
		int i = bpmObservers.indexOf(o);
		if (i >= 0) {
			bpmObservers.remove(i);
		}
	}

	public void notifyBPMObservers() {
		for(int i = 0; i < bpmObservers.size(); i++) {
			BPMObserver observer = (BPMObserver)bpmObservers.get(i);
			observer.updateBPM();
		}
	}
	
	//Devuelve un hash del tipo de modelo (usaod en DJVIew para cambiar etiquetas de botones)
	public int getHash() {
		return 101;
	}
}
